package org.deng.learn.concurrent.basic;

/**
 * Created By DengLibin
 * Date: 19-4-5
 * Time: 下午4:35
 * Desc:位于java.lang包下的Thread类是非常重要的线程类，它实现了Runnable接口.
 * 线程从创建到最终的消亡，要经历若干个状态。一般来说，线程包括以下这几个状态：创建(new)、就绪(runnable)、运行(running)、阻塞(blocked)、time waiting、waiting、消亡（dead）。
 *
 * 　　当需要新起一个线程来执行某个子任务时，就创建了一个线程。但是线程创建之后，不会立即进入就绪状态，因为线程的运行需要一些条件
 * （比如内存资源，譬如程序计数器、Java栈、本地方法栈都是线程私有的，所以需要为线程分配一定的内存空间），只有线程运行需要的所有条件满足了，才进入就绪状态。
 *
 * 　　当线程进入就绪状态后，不代表立刻就能获取CPU执行时间，也许此时CPU正在执行其他的事情，因此它要等待。当得到CPU执行时间之后，线程便真正进入运行状态。
 *
 * 　　线程在运行状态过程中，可能有多个原因导致当前线程不继续运行下去，比如用户主动让线程睡眠（睡眠一定的时间之后再重新执行）、
 * 用户主动让线程等待，或者被同步块给阻塞，此时就对应着多个状态：time waiting（睡眠或等待一定的事件）、waiting（等待被唤醒）、blocked（阻塞）。
 *
 * 　　当由于突然中断或者子任务执行完毕，线程就会被消亡。
 *
 * 1)start()用来启动一个线程，当调用start方法后，系统才会开启一个新的线程来执行用户定义的子任务，在这个过程中，会为相应的线程分配需要的资源
 *
 * 2)run()方法是不需要用户来调用的，当通过start方法启动一个线程之后，当线程获得了CPU执行时间，
 *      便进入run方法体去执行具体的任务。注意，继承Thread类必须重写run方法，在run方法中定义具体要执行的任务。
 *
 * 3)sleep()相当于让线程睡眠，交出CPU，让CPU去执行其他的任务。
 *
 * 　　如果需要让当前正在执行的线程暂停一段时间，并进入阻塞状态，则可以通过调用Thread类的静态sleep()方法来实现。
 *
 * 　　当当前线程调用sleep()方法进入阻塞状态后，在其睡眠时间内，该线程不会获得执行机会，即使系统中没有其他可执行线程，处于sleep()中的线程也不会执行，因此sleep()方法常用来暂停程序的执行
 *
 * 　　但是有一点要非常注意，sleep方法不会释放锁，也就是说如果当前线程持有对某个对象的锁，则即使调用sleep方法，其他线程也无法访问这个对象
 *
 * 4)yield()方法和sleep()方法有点相似，它也是Thread类提供的一个静态方法，它也可以让当前正在执行的线程暂停，但它不会阻塞该线程，它只是将该线程转入到就绪状态。
 *      即让当前线程暂停一下，让系统的线程调度器重新调度一次，完全可能的情况是：当某个线程调用了yield()方法暂停之后，线程调度器又将其调度出来重新执行。
 *
 * 　　调用yield方法会让当前线程交出CPU权限，让CPU去执行其他的线程。它跟sleep方法类似，同样不会释放锁。但是yield不能控制具体的交出CPU的时间，
 *      另外，当某个线程调用了yield()方法之后，只有优先级与当前线程相同或者比当前线程更高的处于就绪状态的线程才会获得执行机会。
 * 　　注意，调用yield方法并不会让线程进入阻塞状态，而是让线程重回就绪状态，它只需要等待重新获取CPU执行时间，这一点是和sleep方法不一样的
 *
 * 5）join方法
 *
 * 　　join方法有三个重载版本：
 *
 * join()
 * join(long millis)     //参数为毫秒
 * join(long millis,int nanoseconds)    //第一参数为毫秒，第二个参数为纳秒
 *
 *  　假如在main线程中，调用thread.join方法，则main方法会等待thread线程执行完毕或者等待一定的时间。如果调用的是无参join方法，则等待thread执行完毕，
 *  如果调用的是指定了时间参数的join方法，则等待一定的时间。
 *
 *  6）interrupt方法
 * 　　interrupt，顾名思义，即中断的意思。单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常，也就说，
 * 它可以用来中断一个正处于阻塞状态的线程；另外，通过interrupt方法和isInterrupted()方法来停止正在运行的线程。
 *
 * 7）interrupted方法　　
 * 　　interrupted()函数是Thread静态方法，用来检测当前线程的interrupt状态，检测完成后，状态清空。
 *
 * 8）stop方法
 * 　　stop方法已经是一个废弃的方法，它是一个不安全的方法。因为调用stop方法会直接终止run方法的调用，并且会抛出一个ThreadDeath错误，如果线程持有某个对象锁的话，会完全释放锁，导致对象状态不一致。所以stop方法基本是不会被用到的。
 * 9）destroy方法
 * 　　destroy方法也是废弃的方法。基本不会被使用到。
 *
 * 以下是关系到线程属性的几个方法：
 * 　　1）getId 用来得到线程ID
 *
 * 　　2）getName和setName 用来得到或者设置线程名称。
 *
 * 　　3）getPriority和setPriority 用来获取和设置线程优先级。
 *
 * 　　4）setDaemon和isDaemon 用来设置线程是否成为守护线程和判断线程是否是守护线程。
 *
 * 　　守护线程和用户线程的区别在于：守护线程依赖于创建它的线程，而用户线程则不依赖。举个简单的例子：如果在main线程中创建了一个守护线程，
 * 当main方法运行完毕之后，守护线程也会随着消亡。而用户线程则不会，用户线程会一直运行直到其运行完毕。在JVM中，像垃圾收集器线程就是守护线程。
 *
 * 　　Thread类有一个比较常用的静态方法currentThread()用来获取当前线程
 *
 */
public class ThreadDemo {

    public  static  void main(String[] args){
        MyThread thread = new MyThread("线程1");
        thread.start();
        System.out.println();
    }

    public  static class MyThread extends Thread{

        public MyThread(String threadName){
            setName(threadName);
        }
        @Override
        public void run() {
            System.out.println(getName() + " 执行了");
        }

    }
}
